﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Bdev.Net.Dns;
using System.Net;
using System.Diagnostics;
using Bdev.Net.Dns.Records;

namespace SampleApplication
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            foreach (IPAddress ip in DnsProvider.SystemDnsServers())
            {
                comboBox1.Items.Add(ip.ToString());
            }
            foreach (IPAddress ip in DnsProvider.DefaultDnsServers)
            {
                comboBox1.Items.Add(ip.ToString());
            }
            if (comboBox1.Items.Count > 0)
                comboBox1.SelectedIndex = 0;

            foreach (DnsClass c in Enum.GetValues(typeof(DnsClass)))
                comboBox2.Items.Add(c);
            comboBox2.SelectedIndex = 0;

            foreach (DnsQType t in Enum.GetValues(typeof(DnsQType)))
                comboBox3.Items.Add(t);
            comboBox3.SelectedIndex = comboBox3.Items.Count - 1;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string query = textBox1.Text;
            IPAddress tIp;

            textBox2.Clear();
            //richTextBox1.AppendText("Looking up " + textBox1.Text + "\r\n");

            try
            {
                // build request
                Request req = new Request();
                DnsClass qclass = (DnsClass)comboBox2.SelectedItem;
                DnsQType qtype = (DnsQType)comboBox3.SelectedItem;
                IPAddress dnsServer;
                if (IPAddress.TryParse((string)comboBox1.Text, out dnsServer) == false)
                {
                    MessageBox.Show("Invalid DNS Server Address", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                if (qtype == DnsQType.PTR && checkBox1.Checked && IPAddress.TryParse(query, out tIp) == true)
                    query = DnsProvider.IpToArpa(tIp);

                Question q = new Question(query, qtype, qclass);
                req.AddQuestion(q);

                // send request to the dns server
                Stopwatch clock = new Stopwatch();
                clock.Start();
                Response r = Resolver.Lookup(req, dnsServer);
                clock.Stop();

                textBox2.AppendText(string.Format("; <<>> Bdev.Net.Dns {0} <<>> @{1} {2} {3}\r\n",
                                                  DnsProvider.Version,
                                                  dnsServer.ToString(),
                                                  qtype.ToString(),
                                                  query));
                textBox2.AppendText(";; global options: none\r\n");

                // check for a response
                if (r == null)
                {
                    textBox2.AppendText("No answer\r\n");
                    return;
                }

                textBox2.AppendText(";; Got answer:\r\n");
                textBox2.AppendText(string.Format(";; ->>HEADER<<- opcode: {0}, status: {1}, id: {2}\r\n",
                                                  req.Opcode.ToString(),
                                                  r.ReturnCode.ToString(),
                                                  r.ID.ToString()));

                textBox2.AppendText(string.Format(";; flags:{0}{1}{2}{3}; QUERY {4}, ANSWER: {5}, AUTHORITY: {6}, ADDITIONAL: {7}\r\n\r\n",
                                                  !r.QR ? " qr" : "",                   // query/response
                                                  r.AuthoritativeAnswer ? " aa" : "",   // authoritative answer
                                                  req.RecursionDesired ? " rd" : "",    // recursion desired
                                                  r.RecursionAvailable ? " ra" : "",    // recursion available
                                                  r.Questions.Length,
                                                  r.Answers.Length,
                                                  r.NameServers.Length,
                                                  r.AdditionalRecords.Length));

                if (r.Questions.Length > 0)
                {
                    textBox2.AppendText(";; QUESTION SECTION:\r\n");
                    foreach (Question rq in r.Questions)
	                {
                        textBox2.AppendText(String.Format(";{0}\t\t\t{1}\t{2}\r\n",
                                                          rq.Domain,
                                                          rq.Class.ToString(),
                                                          rq.QType.ToString())
                                            );
	                }
                    textBox2.AppendText("\r\n");
                }

                if (r.Answers.Length > 0)
                {
                    textBox2.AppendText(";; ANSWER SECTION:\r\n");
                    foreach (Answer ra in r.Answers)
                    {
                        textBox2.AppendText(String.Format("{0,-32}{1}\t{2}\t{3}\t{4}\r\n",
                                                          ra.Domain,
                                                          ra.Ttl.ToString(),
                                                          ra.Class.ToString(),
                                                          ra.Type.ToString(),
                                                          ra.Record.ToString())
                                            );
                    }
                    textBox2.AppendText("\r\n");
                }

                if (r.NameServers.Length > 0)
                {
                    textBox2.AppendText(";; AUTHORITY SECTION:\r\n");
                    foreach (NameServer rn in r.NameServers)
                    {
                        textBox2.AppendText(String.Format("{0,-32}{1}\t{2}\t{3}\t{4}\r\n",
                                                          rn.Domain,
                                                          rn.Ttl.ToString(),
                                                          rn.Class.ToString(),
                                                          rn.Type.ToString(),
                                                          rn.Record.ToString())
                                            );
                    }
                    textBox2.AppendText("\r\n");
                }

                if (r.AdditionalRecords.Length > 0)
                {
                    textBox2.AppendText(";; ADDITIONAL SECTION:\r\n");
                    foreach (AdditionalRecord ra in r.AdditionalRecords)
                    {
                        textBox2.AppendText(String.Format("{0,-32}{1}\t{2}\t{3}\t{4}\r\n",
                                                          ra.Domain,
                                                          ra.Ttl.ToString(),
                                                          ra.Class.ToString(),
                                                          ra.Type.ToString(),
                                                          ra.Record.ToString())
                                            );
                    }
                    textBox2.AppendText("\r\n");
                }

                textBox2.AppendText(String.Format(";; Query time: {0} msec\r\n", clock.ElapsedMilliseconds));
                textBox2.AppendText(String.Format(";; SERVER: {0}#{1}({2})\r\n", dnsServer.ToString(), 53, dnsServer.ToString()));
                textBox2.AppendText(String.Format(";; WHEN: {0}\r\n", DateTime.Now.ToString("ddd MMM dd HH:mm:ss yyyy")));
                //TODO: MessageSize is not giving correct info...
                textBox2.AppendText(String.Format(";; MSG SIZE  rcvd: {0}\r\n", r.MessageSize));
            }
            catch (Exception ex)
            {
                textBox2.AppendText("An error ocurred\r\n\r\n" + ex.ToString());
            }
        }
    }
}
